/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.di.ban.jr.swb.rest.mq.utils;

import cn.ac.iie.di.ban.jr.swb.rest.mq.global.GlobalParas;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Timer;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.log4j.Logger;

/**
 *
 * @author zwlin
 */
public class FileAppender {
    
    private static HashMap<String, FileAppender> appenderMap = new HashMap<>();
    public static Logger LOG = Logger.getLogger(FileAppender.class);
    
    public static synchronized void register(String name, FileAppender appender) {
        appenderMap.put(name, appender);
    }
    
    public static FileAppender getAppender(String name) {
        return appenderMap.get(name);
    }
    
    private static final String SPLITTER = ".";
    boolean activated;
    
    File dir;
    String fileDir;
    HashMap<String, String> nameMap;
    int maxSize;
    int interval;
    
    long last;
    
    int size;
    int seq;
    
    long startTime;
    long endTime;
    
    BufferedWriter bw;
    
    ReentrantLock lock;
    
    public FileAppender(String dirString, String filename, int size, int interval) throws IOException {
        try {
            initArg(dirString, filename, size, interval);
            initDefault();
            passOldFiles();
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }

//		bw = new BufferedWriter(new FileWriter(new File(dir, name + SPLITTER + seq)));
    }
    
    private void initArg(String dirString, String filename, int size, int interval) {
        this.dir = new File(dirString);
        if (!this.dir.exists()) {
            if (!this.dir.mkdirs()) {
                throw new Error("cannot mkdir dir path:" + dirString);
            }
        } else if (!dir.isDirectory()) {
            throw new Error("dir path:" + dirString + " is not a directory.");
        }
        this.fileDir = dirString;
//		this.nameMap = filename == null ? "" : filename;
        this.maxSize = size * 1024 * 1024 / 4;
        this.interval = interval * 60 * 1000;
        this.startTime = System.currentTimeMillis();
    }
    
    private void initDefault() {
        
        last = Long.MAX_VALUE;
        size = 0;
        seq = 0;
        lock = new ReentrantLock();
        activated = false;
    }
    
    private void passOldFiles() {
        String[] files = dir.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
//				return name != null && name.startsWith(FileAppender.this.name);
                return false;
            }
        });
        int max = -1;
        for (String f : files) {
            String[] dvd = f.split(SPLITTER);
            if (dvd.length == 2) {
                try {
                    int v = Integer.parseInt(dvd[1].trim());
                    if (v > max) {
                        max = v;
                    }
                } catch (Exception e) {
                }
            }
        }
        seq = max + 1;
    }
    
    public void start() {
//		timer.schedule(new ChangeFileTask(), interval);
        activated = true;
    }
    
    public void stop() throws IOException {
        activated = false;
//		bw.flush();
//		bw.close();
    }

//	class ChangeFileTask extends TimerTask {
//
//		@Override
//		public void run() {
//			if (System.currentTimeMillis() - last >= interval) {
//				lock.lock();
//				try {
//					if (System.currentTimeMillis() - last >= interval && size > 0) {
//						changeFile();
//					}
//					timer.schedule(ChangeFileTask.this, last + interval - System.currentTimeMillis());
//
//				} catch (IOException ex) {
//					throw new Error(ex);
//				} finally {
//					lock.unlock();
//				}
//			}
//		}
//	}
//写文件，把请求内容写文件中，文件写入本地
    public synchronized void append(String datatype, String str) throws IOException {
        if (!activated) {
            throw new Error("FileAppender is closed!");
        }
        lock.lock();
        try {
//			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
//			fileDir = GlobalParas.FILE_DIR + sdf.format(System.currentTimeMillis()) + "/";
            fileDir = WriteFile.getFileDir(GlobalParas.FILE_DIR, datatype);
            endTime = System.currentTimeMillis();
            if (nameMap == null) {
                nameMap = new HashMap<>();
            }
//            if (size > maxSize || endTime - startTime > interval) {
//                nameMap.put(datatype, WriteFile.getFileName("wxyq_" + datatype + "_"));
//                size = 0;
//                startTime = endTime;
//            }
            File f = new File(fileDir + nameMap.get(datatype));
            
            if (f.length() > maxSize || endTime - startTime > interval) {
                nameMap.put(datatype, WriteFile.getFileName("wxyq_" + datatype + "_"));
                LOG.info("put to nameMap :" + "wxyq_" + datatype + "_");
            }
            if (nameMap.size() == 0) {
                nameMap.put(datatype, WriteFile.getFileName("wxyq_" + datatype + "_"));
                LOG.info("put to nameMap :" + "wxyq_" + datatype + "_");
            }
            size += str.length();
            LOG.info("start to write to file :" + fileDir + nameMap.get(datatype));
            WriteFile writeFile = new WriteFile(fileDir, nameMap.get(datatype));
            writeFile.writeFileAppend(datatype, str);
//			bw.write(str);
//			bw.newLine();
            last = System.currentTimeMillis();
            LOG.info("use time " + (last - endTime) + " ms");
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        } finally {
            lock.unlock();
        }
    }
    
    public String getFileDir() {
        return fileDir;
    }

//	public String getName() {
////		return name;
////	}
//	private synchronized void changeFile() throws IOException {
////		bw.flush();
////		bw.close();
////		bw = new BufferedWriter(new FileWriter(new File(dir, name + SPLITTER + (++seq))));
//		Date date = new Date();
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
//		String dateNowStr = sdf.format(date);
//		name = "wxyq_dayhot_" + dateNowStr;
//		size = 0;
//	}
}
